﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml;
using Brjnk.Common;
using Brjnk.GpxExplorer.Data;
using Brjnk.GpxExplorer.Workspace;
using Brjnk.GpxExplorer.Workspace.Searching;

namespace Brjnk.GpxExplorer.UI
{
    /// <summary>
    /// Interaction logic for SearchPlaceWindow.xaml
    /// </summary>
    public partial class SearchPlaceWindow : Window, INotifyPropertyChanged
    {
        private PushpinsManager pushpins;

        public SearchPlaceWindow(PushpinsManager pushpins)
        {
            this.pushpins = pushpins;
            InitializeComponent();
            GenerateCountries();
            CreateCommands();
        }

        private void GenerateCountries()
        {
            Regions = CountryInfo.GetAllRegions().ToList();
            SelectedRegion = RegionInfo.CurrentRegion;
        }

        private Uri GetUrl()
        {
            if (string.IsNullOrEmpty(SearchedString)) return new Uri(string.Empty);
            //  var name = System.Web.HttpUtility.UrlEncode(value.ToString());
            var uri = string.Format(GetPattern(), GetModeParameter(), SearchedString, GetCountyParameter());
            return new Uri(uri);
        }

        private string GetCountyParameter()
        {
            if ((object)SelectedRegion == null || !FilterByCountry) return string.Empty;
            else return string.Format("country={0}&", SelectedRegion.TwoLetterISORegionName);
        }

        private string GetModeParameter()
        {
            switch (Mode)
            {
                case SearchPlaceMode.AllAttributes:
                    return "q"; ;
                case SearchPlaceMode.OnlyByName:
                    return "name";
                case SearchPlaceMode.ExactName:
                    return "name_equals";
                case SearchPlaceMode.NameStartsWith:
                    return "name_startsWith";
                default:
                    throw new Exception("Unknown value of SearchPlaceMode.");
            }
        }

        private string GetPattern()
        {
            return "http://api.geonames.org/search?{0}={1}&{2}maxRows=50&username=gpxexplorer";
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var xmlProvider = (XmlDataProvider)this.FindResource("xmlData");
            xmlProvider.Source = GetUrl();
            xmlProvider.Refresh();
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            this.Close();
            //this.DialogResult = false;
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            foreach (XmlElement element in items.SelectedItems)
            {
                var info = GeoNamesHelper.GetPlaceInfo(element);
                var gps = new GpsCoordinates(info.Position.LatTotalDegree, info.Position.LonTotalDegree);
                AddRequest(info.Name, gps);
                if (CreateWaypoint)
                    AddWaypoint(info.Name, gps);
            }
            this.Close();
            //this.DialogResult = true;
        }

        private void AddWaypoint(string name, GpsCoordinates gps)
        {
            var data = new WaypointDefault();
            data.Name = name;
            data.Position = gps;
            var wpt = new Brjnk.GpxExplorer.ViewModel.WaypointVM(data);
            App.Instance.Workspace.Data.Waypoints.Add(wpt);
        }

        private void AddRequest(string name, GpsCoordinates coordinates)
        {
            App.Instance.Workspace.SearchService.SearchedItems.Add(new SearchPlaceRequest(name)
            {
                MaxDistance = searchArgs.Limit,
                ShowAgainDistance = searchArgs.SearchAgainLimit,
                Position = coordinates,
                SearchInGaps = searchArgs.SearchInGaps,
                Color1 = SearchRequestColor,
                Color2 = Colors.Black
            });
        }

        private void Image_MouseDown(object sender, MouseButtonEventArgs e)
        {
            System.Diagnostics.Process.Start("http://www.geonames.org/");
        }

        private string searchedString;

        public string SearchedString
        {
            get { return searchedString; }
            set { searchedString = value; OnPropertyChanged("SearchedString"); }
        }

        private SearchPlaceMode mode;

        public SearchPlaceMode Mode
        {
            get { return mode; }
            set { mode = value; OnPropertyChanged("Mode"); }
        }

        private List<RegionInfo> regions;

        public List<RegionInfo> Regions
        {
            get { return regions; }
            set { regions = value; OnPropertyChanged("Regions"); }
        }

        private RegionInfo selectedRegion;

        public RegionInfo SelectedRegion
        {
            get { return selectedRegion; }
            set { selectedRegion = value; OnPropertyChanged("SelectedRegion"); }
        }

        private Color searchRequestColor = Colors.Brown;

        public Color SearchRequestColor
        {
            get { return searchRequestColor; }
            set { searchRequestColor = value; OnPropertyChanged("SearchRequestColor"); }
        }

        private bool createWaypoint;

        public bool CreateWaypoint
        {
            get { return createWaypoint; }
            set { createWaypoint = value; OnPropertyChanged("CreateWaypoint"); }
        }

        private bool filterByCountry;

        public bool FilterByCountry
        {
            get { return filterByCountry; }
            set { filterByCountry = value; OnPropertyChanged("FilterByCountry"); }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #region Commands

        private void CreateCommands()
        {
            GoCommand = new GenericCommand(Go);
            GoBigZoomCommand = new GenericCommand(GoBigZoom);
        }

        private void Go(object arg)
        {
            if (!(arg is XmlElement)) return;
            var info = GeoNamesHelper.GetPlaceInfo(arg as XmlElement);
            pushpins.AddPushpinAndGo(info.Position, info.Name, false);
        }

        private void GoBigZoom(object arg)
        {
            if (!(arg is XmlElement)) return;
            var info = GeoNamesHelper.GetPlaceInfo(arg as XmlElement);
            pushpins.AddPushpinAndGo(info.Position, info.Name, true);
        }

        public GenericCommand GoCommand { get; private set; }

        public GenericCommand GoBigZoomCommand { get; private set; }

        #endregion Commands
    }

    public enum SearchPlaceMode
    {
        AllAttributes,
        OnlyByName,
        ExactName,
        NameStartsWith
    }
}